#pragma once
#include <iostream>
#include <chrono>

enum PlayerSatus
{
    Exist,
    NonExistent
};

const double degrees_per_second = 300.0;
const double radians_per_second = degrees_per_second * g_pi / 180.0;
double initial_radian = 0;
const int clockwise = 1;
const int anticlockwise = -1;

class Sword
{
public:
    Sword()
    {
        _timer = std::chrono::high_resolution_clock::now();
    }

    void Move()
    {
        auto time = std::chrono::high_resolution_clock::now();
        ////_timer += frames_time;
        std::chrono::duration<double> delta_time = time - _timer;
        _timer = time;
        //_radian += rotation_direction * radians_per_second * ((300 - g_countdown) / 1000);
        _radian += rotation_direction * radians_per_second * delta_time.count();
    }

    int rotation_direction = clockwise;
    double _radian = initial_radian;
    std::chrono::high_resolution_clock::time_point _timer;
};

class Player
{
public:
    Player() : _id(0), _conn(nullptr), _exist(PlayerSatus::NonExistent) {}

    Player(int id, PlayerSatus exist, Connection *conn) : _id(id), _conn(conn), _exist(exist) {}
    Player(const Player &play)
    {
        _conn = play._conn;
        _id = play._id;
        _exist = play._exist;
    }

    void SetStatus(PlayerSatus exist)
    {
        _exist = exist;
    }

    bool Exist()
    {
        return _exist == PlayerSatus::Exist;
    }

    void SetId(int id)
    {
        _id = id;
    }

    int GetId()
    {
        return _id;
    }

    bool Ready()
    {
        return _ready;
    }

    void SetReady(bool ready)
    {
        _ready = ready;
    }

    void Move(double x, double y)
    {
        if ((_x + x - g_radius >= 0) && _x + x + g_radius <= window_width)
            _x += x;
        else
        {
            if (_x + x - g_radius < 0)
                _x = g_radius;
            if (_x + x + g_radius > window_width)
                _x = window_width - g_radius;
        }
        if ((_y + y - g_radius >= 0) && _y + y + g_radius <= window_height)
            _y += y;
        else
        {
            if (_y + y - g_radius >= 0 < 0)
                _y = g_radius;
            if (_y + y + g_radius > window_height)
                _y = window_height - g_radius;
        }
    }

    Connection *GetConnection()
    {
        return _conn;
    }

    ~Player() {}

    double _x = 0, _y = 0;
    int _color = 0;

    Sword _sword;

private:
    int _id;
    Connection *_conn;
    PlayerSatus _exist;

    bool _ready = false;
};

class Room
{
public:
    Room(std::string number, int max_number) : _number(number), _max_member(max_number)
    {
        _players.resize(max_number);
    }

    void InitPlayerCoor(int player_index)
    {
        int y = 7;
        int x = 0;
        switch (_max_member)
        {
        case 2:
            if (player_index >= 1)
                y = 23;
            x = 24;

            _players[player_index]._x = x * 20 + g_radius;
            _players[player_index]._y = y * 20 + g_radius;
            _players[player_index]._color = player_index;

            break;
        case 4:
        {
            if (player_index >= 2)
                y = 23;
            x = player_index % 2 == 0 ? 12 : 36;

            _players[player_index]._x = x * 20 + g_radius;
            _players[player_index]._y = y * 20 + g_radius;
            _players[player_index]._color = player_index;
        }
        break;
        case 8:
            if (player_index >= 4)
                y = 23;
            x = 5 + (12 * (player_index % 4));

            _players[player_index]._x = x * 20 + g_radius;
            _players[player_index]._y = y * 20 + g_radius;
            _players[player_index]._color = player_index;

            break;
        default:
            break;
        }
    }

    // 返回的值时此时加入房间的玩家的player_id
    int AddPlayer(Connection *conn)
    {
        for (int i = 0; i < _max_member; i++)
        {
            if (!_players[i].Exist())
            {
                _players[i] = Player(i, Exist, conn);
                // std::cout << "Add player: " << i << std::endl;
                cur_member_number.push_back(i + '0');
                InitPlayerCoor(i);
                // std::cout << "cur_member_number: " << cur_member_number << std::endl;
                // std::cout << "_players[1].Exist()" << _players[1].Exist() << std::endl;
                return i;
            }
        }
        return -1;
    }

    void DelPlayer(Connection *conn)
    {
        for (int i = 0; i < _max_member; i++)
        {
            if (_players[i].Exist() && _players[i].GetConnection() == conn)
            {
                _players[i] = Player(-1, NonExistent, nullptr);
                // std::cout << "Del player: " << i << std::endl;
                for (int j = 0; j < cur_member_number.size(); j++)
                {
                    if (cur_member_number[j] - '0' == i)
                    {
                        std::swap(cur_member_number[j], cur_member_number[cur_member_number.size() - 1]);
                        cur_member_number.pop_back();
                    }
                }
                // std::cout << "cur_member_number: " << cur_member_number << std::endl;
                // std::cout << "_players[1].Exist()" << _players[1].Exist() << std::endl;
                return;
            }
        }
    }
    std::vector<Player> &GetPlayers()
    {
        return _players;
    }

    std::string GetPlayersNumber()
    {
        return cur_member_number;
    }

    void SetStartDownCount(time_t time_stamp)
    {
        _start_downcount = time_stamp;
    }

    time_t GetStartDownCount()
    {
        return _start_downcount;
    }

    int GetMaxMember()
    {
        return _max_member;
    }

    ~Room() {}

private:
    time_t _start_downcount;
    // std::chrono::time_point<std::chrono::high_resolution_clock> _start_downcount;

    std::string _number;
    int _max_member;
    std::string cur_member_number;

    std::vector<Player> _players;
};
